#include <iostream>
#include <string.h>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"


using work_t = std::function<void()>;

enum
{
    OK=0,
    UsageError,
    PipeError,
    ForkError
};

class Channel
{
public:
    Channel(int wfd,pid_t who):_wfd(wfd),_who(who)
    {
        //Channel-3-1234
        _name = "Channel-" + std::to_string(wfd) + "-" + std::to_string(who);
    }
    std::string Name()
    {
        return _name;
    }
    void Send(int cmd)
    {
        write(_wfd,&cmd,sizeof(cmd));
    }
    void Close()
    {
        close(_wfd);
    }
    pid_t Id()
    {
        return _who;
    }
    ~Channel()
    {}
private:
    int _wfd;
    std::string _name;
    pid_t _who;
};

void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << " process-num" << std::endl;
}

void Worker()
{
    while(true)
    {
        int cmd = 0;
        int n = read(0,&cmd,sizeof(cmd));
        if(n == sizeof(cmd))
        {
            tm.Excute(cmd);
        }
        else if(n == 0)
        {
            std::cout << "pid: " << getpid() << " quit..." << std::endl;
            break;
        }
        else
        {

        }
    }
}

//work_t : 是回调方法
int InitProcessPool(const int& processnum,std::vector<Channel>& channels,work_t work)
{
    for(int i = 0;i < processnum;i++)
    {
        //1.先有管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if(n < 0)
        {
            return PipeError;
        }
        //2.创建进程
        pid_t id = fork();
        if(id < 0)
        {
            return ForkError;
        }
        //3.建立通信信道
        if(id == 0)
        {
            close(pipefd[1]);//read
            //child
            dup2(pipefd[0],0);
            work();
            exit(0);
        }
        //父进程执行
        close(pipefd[0]);//write
        channels.emplace_back(pipefd[1],id);
    }
    return OK;
}

void DebugPrint(std::vector<Channel>& channels)
{
    for(auto& c : channels)
    {
        std::cout << c.Name() << std::endl;
    }
}

void DispatchTask(std::vector<Channel>& channels)
{
    //2.派发任务
    int who = 0;
    int num = 20;
    while(num--)
    {
        //a.选择一个任务,整数
        int task = tm.SelectTask();
        //b.选择一个子进程channel
        Channel& curr = channels[who++];
        who %= channels.size();
        std::cout << "#######################" << std::endl;
        std::cout << "send " << task << " to" << curr.Name() << ", 任务还剩: " << num << std::endl;
        std::cout << "#######################" << std::endl;
        //c.派发任务
        curr.Send(task);
        sleep(1);
    }
}


void CleanProcessPool(std::vector<Channel>& channels)
{
    for(auto& c:channels)
    {
        c.Close();
    }
    for(auto& c:channels)
    {
        pid_t rid = waitpid(c.Id(),nullptr,0);
        if(rid > 0)
        {
            std::cout << "child " << rid << " wait ... success" << std::endl;
        }
    }
}

//我们自己就是主进程
int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    int num = std::stoi(argv[1]);
    std::vector<Channel> channels;
    //1.初始化进程池
    InitProcessPool(num,channels,Worker);
    //2.派发任务
    DispatchTask(channels);
    //3.退出子进程
    CleanProcessPool(channels);

    return 0;
}